import pygame

from PyPixelCore.Setting import Block_type, show_rect_collision, Color_type, collision_surface_width, \
    block_surface_width, fps_limit
from PyPixelCore.block.TextBlock import TextBlock
from PyPixelCore.timer.FrequencyTimer import FrequencyTimer

"""
    TextButton --> TextBlock --> Block --> BaseBlock
    基础的文字按钮
    可直接使用或者继承优化
    功能:
        显示文字
        支持碰撞检测
        支持帧函数与计时器函数
        支持点击事件
        支持鼠标移入移出事件
        不支持自动换行绘制
        支持脏精灵优化
"""


class TextButton(TextBlock):
    def __init__(self, text_content="未定义按钮", point_x=0, point_y=0, width=0, height=0, border_width=2, layer=0,
                 is_alpha=False):
        self.text_surf = None
        self.clicked_func = None
        self.width = width
        self.height = height
        self.click_down_func = basic_mouse_down
        self.click_up_func = basic_mouse_up
        self._is_clicked = False  # 选择使用,用于在选择按钮上
        self.hover_color = Color_type.LIGHT_GREY
        self.press_color = Color_type.GREY
        super().__init__(text_content, point_x, point_y, border_width, layer, is_alpha)
        self._type = Block_type.button

    def update(self):
        self.reload_image()
        # 帧函数的调用
        if self.update_func:
            self.update_func(self)
        # 帧计时器函数的调用
        if self.timer_arr:
            for timer_group in self.timer_arr:
                timer_group[0].next_frame()
                if timer_group[0].is_end:
                    timer_group[1](self)
                    if timer_group[0].type == 0:  # 一次性循环则删除不参与reset
                        self.timer_arr.remove(timer_group)
                    else:
                        timer_group[0].reset()


    def mouse_hover_enter(self):
        self.change_color = [(self.hover_color[0] - self.bk_color[0]) / fps_limit * 4,
                             (self.hover_color[1] - self.bk_color[1]) / fps_limit * 4,
                             (self.hover_color[2] - self.bk_color[2]) / fps_limit * 4]
        self.sum_color = [0.0, 0.0, 0.0]

        def change_color(t_self: TextButton):
            t_self.sum_color = [t_self.sum_color[0] + t_self.change_color[0],
                                t_self.sum_color[1] + t_self.change_color[1],
                                t_self.sum_color[2] + t_self.change_color[2]]
            t_self.now_bk_color = [t_self.now_bk_color[0] + t_self.sum_color[0] // 1,
                                   t_self.now_bk_color[1] + t_self.sum_color[1] // 1,
                                   t_self.now_bk_color[2] + t_self.sum_color[2] // 1]
            t_self.sum_color = [t_self.sum_color[0] % 1,
                                t_self.sum_color[1] % 1,
                                t_self.sum_color[2] % 1]
            # self.image.fill(self.now_color)
            if t_self.now_bk_color[0] - t_self.hover_color[0] < 1 and t_self.now_bk_color[1] - t_self.hover_color[1] < 1 and \
                    t_self.now_bk_color[2] - t_self.hover_color[2] < 1:
                t_self.now_bk_color = t_self.hover_color
                t_self.set_frame_animation(None)
            t_self.is_dirty = True

        self.set_frame_animation(change_color)

    def mouse_hover_leave(self):
        self.change_color = [(self.bk_color[0] - self.hover_color[0]) / fps_limit * 4,
                             (self.bk_color[1] - self.hover_color[1]) / fps_limit * 4,
                             (self.bk_color[2] - self.hover_color[2]) / fps_limit * 4]
        self.sum_color = [0.0, 0.0, 0.0]

        def change_color(t_self: TextButton):
            t_self.sum_color = [t_self.sum_color[0] + t_self.change_color[0],
                                t_self.sum_color[1] + t_self.change_color[1],
                                t_self.sum_color[2] + t_self.change_color[2]]
            t_self.now_bk_color = [t_self.now_bk_color[0] + t_self.sum_color[0] // 1,
                                   t_self.now_bk_color[1] + t_self.sum_color[1] // 1,
                                   t_self.now_bk_color[2] + t_self.sum_color[2] // 1]
            t_self.sum_color = [t_self.sum_color[0] % 1,
                                t_self.sum_color[1] % 1,
                                t_self.sum_color[2] % 1]
            # self.image.fill(self.now_color)
            t_self.is_dirty = True
            if t_self.now_bk_color[0] - t_self.hover_color[0] < 1 and t_self.now_bk_color[1] - t_self.hover_color[1] < 1 and \
                    t_self.now_bk_color[2] - t_self.hover_color[2] < 1:
                t_self.now_bk_color = t_self.bk_color
                t_self.set_frame_animation(None)

            if t_self.now_bk_color[0] < 256 and t_self.now_bk_color[1] < 256 and t_self.now_bk_color[2] < 256:
                pass
            else:
                t_self.now_bk_color = t_self.bk_color
                t_self.set_frame_animation(None)

        self.set_frame_animation(change_color)

    def click_down(self, pos):
        self.click_down_func(self)
        self.now_bk_color = self.press_color
        self.set_frame_animation(None)
        self.is_dirty = True

    def click_up(self):
        self.click_up_func(self)
        self.now_bk_color = self.hover_color
        self.is_dirty = True

    def set_click_down_func(self, func):
        self.click_down_func = func

    def set_click_up_func(self, func):
        self.click_up_func = func

    def set_color_no_None(self, font_color=None, bk_color=None, border_color=None, hover_color=None, press_color=None):
        if font_color is not None:
            self.font_color = font_color
        if bk_color is not None:
            self.bk_color = bk_color
        if border_color is not None:
            self.border_color = border_color
        if hover_color is not None:
            self.hover_color = hover_color
        if press_color is not None:
            self.press_color = press_color
        self.is_dirty = True

    def _reload_image_first(self):
        self.now_bk_color = self.bk_color
        self.text_surf = self.font.render(self.text_content, True, self.font_color)
        t_width = self.text_surf.get_size()[0] + 2 * self.border_width \
            if self.width == 0 else self.width + 2 * self.border_width
        t_height = self.text_surf.get_size()[1] + 2 * self.border_width \
            if self.height == 0 else self.height + 2 * self.border_width
        if self.is_alpha:
            self.image = pygame.Surface((t_width, t_height), pygame.SRCALPHA)
        else:
            self.image = pygame.Surface((t_width, t_height))
        self.image.fill(self.now_bk_color)
        self.rect.size = self.image.get_size()
        # 绘制方框到主图上
        if self.border_width != 0:
            pygame.draw.rect(self.image, self.border_color,
                         (0, 0, self.rect.width, self.rect.height), width=self.border_width)
        # 绘制文字到主图上
        self.image.blit(self.text_surf,
                        ((self.rect.w - self.text_surf.get_size()[0]) // 2,
                         (self.rect.h - self.text_surf.get_size()[1]) // 2,
                         self.rect.width, self.rect.height))
        self.collision_rect = self.rect.copy()

    def reload_image(self):  # 可以优化: 分离出font.render
        if not self.is_dirty:
            return
        self.is_dirty = False
        self.image.fill(self.now_bk_color)
        # 绘制方框到主图上
        pygame.draw.rect(self.image, self.border_color,
                         (0, 0, self.rect.width, self.rect.height), width=self.border_width)
        # 绘制文字到主图上
        self.image.blit(self.text_surf,
                        ((self.rect.w - self.text_surf.get_size()[0]) // 2,
                         (self.rect.h - self.text_surf.get_size()[1]) // 2,
                         self.rect.width, self.rect.height))

    def reload_text_surf(self):
        self.text_surf = self.font.render(self.text_content, True, self.font_color)
        t_width = self.text_surf.get_size()[0] + 2 * self.border_width \
            if self.width == 0 else self.width + 2 * self.border_width
        t_height = self.text_surf.get_size()[1] + 2 * self.border_width \
            if self.height == 0 else self.height + 2 * self.border_width
        if self.is_alpha:
            self.image = pygame.Surface((t_width, t_height), pygame.SRCALPHA)
        else:
            self.image = pygame.Surface((t_width, t_height))
        self.image.fill(self.now_bk_color)
        self.rect.size = self.image.get_size()
        self.collision_rect = self.rect.copy()

    def set_text_content(self, text_content):
        self._text_content = text_content
        self.reload_text_surf()
        self.is_dirty = True

    def draw(self, surf):
        base_draw(self, surf)


def base_draw(self: TextBlock, surf):
    surf.blit(self.image, self.rect)
    if show_rect_collision:
        pygame.draw.rect(surf, Color_type.RED, self.rect, width=block_surface_width)


def basic_mouse_down(self: TextButton):
    print(f"{self} 未定义鼠标点击事件")


def basic_mouse_up(self: TextButton):
    print(f"{self} 未定义鼠标松开事件")
